#ifndef UNREALSTREAM_H
#define UNREALSTREAM_H
#include "main.h"


using namespace std;
using namespace Gio;
using namespace Glib;

class UnrealPlace;
struct Command;

class UnrealStream{
    public:
        typedef vector<pair<string, string> >::iterator FieldIter;
        /** Default constructor */
        UnrealStream(const RefPtr<DataInputStream>& is, const RefPtr<DataOutputStream>& os);
        /** nextMessage
        skips ahead to the next message, and returns it
        */
        string nextMessage();
        /** CurrentMessage
        * returns the name of the current message
        */
        string currentMessage();
        /** fieldcount
            the number of fields in the message
        */
        int fieldCount();
        void putCommand(string cmd);

        pair<string, string> operator[](int pos);


        /** readUntil
            reads until the given \c Message
            other than that equal to nextMessage
            be carefull with this one, it might just continue if it doesn't find \c message
        */
        bool readUntil(string Message);
        vector<pair<string, string> > fields;
        /** Default destructor */
        virtual ~UnrealStream();

        /** matchVal
            the int representation of the messageName
            it is the first 3 chars in reverse order
            it can be used like:
            \code{.cpp}
            switch(matchval){
                case 'OFN':
                //do something with the NFO command
            }
            \endcode
        */

        unsigned matchVal();

        void queueCommand(Command* cmd);
        UnrealStream& operator<<(Command& cmd);
        void sendCommand(Command* cmd);
        void sendCommandDelete(Command* cmd);
        void flushCommands();


    protected:
        RefPtr<DataInputStream> is;
        RefPtr<DataOutputStream> os;

        vector<Command*> commandQueue;
        string MessName;

    private:
};



struct Command{
    string param(const char name[], int val){
        return string("{") + name + " " + ustring::compose("%1", val) + "} ";
    }
    string param(const char name[], bool val){
        return string("{") + name + (val?" True} ":" False} ") ;
    }
    string param(const char name[], string val){
        return string("{") + name + " " + (val) + "} ";
    }
    string param(const char name[], UnrealPlace val);
    virtual string make() =0;

    operator string (){
        return make();
    }
};


///////////////////////some messages to send

struct AddBotCommand:public Command{
    string name;
    string startLocation;
    int skill;
    int team;
    virtual string make(){
        return "ADDBOT " +
            param("Name", name) +
            param("StartLocation", startLocation)+
            param("Skill", skill) +
            param("Team",  team) + "\r\n";
    }
};
struct GetMapsCommand:public Command{
	virtual string make(){
		return "GETMAPS\r\n";
	}
};
struct ChangeMapCommand:public Command{
	string mapName;
	ChangeMapCommand(string name){
		mapName = name;
	}
	virtual string make(){
		return "CHANGEMAP " + param("MapName", mapName) + "\r\n";
	}
};


#endif // UNREALSTREAM_H
